;
; Copyright (c) Microsoft Corporation.  All rights reserved.
;
;
; Use of this sample source code is subject to the terms of the Microsoft
; license agreement under which you licensed this sample source code. If
; you did not accept the terms of the license agreement, you are not
; authorized to use this sample source code. For the terms of the license,
; please see the license agreement between you and Microsoft or, if applicable,
; see the LICENSE.RTF on your install media or the root of your tools installation.
; THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
;
;
; (C) Copyright 2006 Marvell International Ltd.
; All Rights Reserved
;
;------------------------------------------------------------------------------
;
;   File:  startup.s
;
;   Kernel startup routine for the Intel Zylonite board.
;
;------------------------------------------------------------------------------

    INCLUDE kxarm.h
    INCLUDE littleton.inc
    INCLUDE image_cfg.inc
    
    IMPORT  KernelStart

    TEXTAREA
       
;------------------------------------------------------------------------
    
     
    ; Include memory configuration file with g_oalAddressTable
    ;
    INCLUDE oemaddrtab_cfg.inc
 
;-------------------------------------------------------------------------------
;
; OALStartUp: OEM OAL startup code.
;
; Inputs: None.
; 
; On return: N/A.
;
; Register used: r0
;
;-------------------------------------------------------------------------------
;
    ALIGN
    LEAF_ENTRY OALStartUp
	IMPORT IsL2Enable
	
		
    ; Initialize the hex LEDs on the Zylonite board.  These use GPIOs which were
    ; configured in the OALXScaleSetFrequencies callback during clock initialization.
    ;
    ;bl      Init_HexLEDs

	; 
    ;ldr     r4, =0x40100000                 
    ;mov   r12, #0x39
    ;strb   r12, [r4, #0]

    ldr     sp, =IMAGE_BOOT_STACK_RAM_PA_START   ;set a temp static to call a C function
	BL IsL2Enable
	cmp r0, #0
	beq L2FINISH
	
 IF :DEF: USING_L2_CACHE
 
    ; pre-set L2 cache enabling in MMU
    mrc		p15, 0, r0, c1, c0, 0
    orr		r0, r0, #0x04000000
    mcr		p15, 0, r0, c1, c0, 0

    mov r0, #0x7F00
    orr r0, r0, #0x00E0        ; put NSets (256)-1 into bits 12:5, way 0
1
	mov	r1, r0
5	
	mcr p15, 1, r1, c7, c15, 2  ; clean&inv set/way of L2 dcache specified in r1
    cmp r1, #0xd0000000
    addlo r1, r1, #0x20000000
    blo %BT5 
    
    subs r0, r0, #0x00000020   ; decrement the shifted set index (way0)
    bpl %BT1  
    
    ; set up a data write barrier
    mcr     p15, 0, r0, c7, c10, 4
    
 ENDIF ;IF :DEF: USING_L2_CACHE
    
    ; Compute the OEMAddressTable's physical address and 
    ; load it into r0. KernelStart expects r0 to contain
    ; the physical address of this table. The MMU isn't 
    ; turned on until well into KernelStart.  
    ;

L2FINISH

    add     r0, pc, #g_oalAddressTable - (. + 8)
    mov     r11, r0
    bl      KernelStart
    
    nop
    nop
    nop
    nop
    nop
    nop
    
STALL
	; 
    ldr     r4, =0x40100000                 
    mov   r12, #0x53
    strb   r12, [r4, #0]

    b       STALL               ; Spin forever.


;-------------------------------------------------------------------------------
;
; Init_HexLEDs: Initializes the Zylonite board logic to enable the hex LEDs.
;
; Inputs: None.
; 
; On return: N/A.
;
; Register used: r0-r3
;
;-------------------------------------------------------------------------------
;
    ALIGN
Init_HexLEDs


  IF Interworking :LOR: Thumbing
    bx       lr
  ELSE
    mov      pc, lr                           ; Return to caller.
  ENDIF



;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------

    LTORG                           ; insert a literal pool here.

;-------------------------------------------------------------------------------
;
; TURN_ON_BTB: Enables the branch target buffer.  Does a global invalidate first.
;
; Inputs: None.
; 
; On return: N/A.
;
; Register used: r0, r1.  Stacked on caller's stack.
;
;-------------------------------------------------------------------------------
;
    LEAF_ENTRY TURN_ON_BTB

    stmfd   sp!, {r0-r1}
    
    mcr  p15, 0, r0, c7, c5, 0   ; flush L1i$ and BTB.  R0 is ignored.
        
    ldr  r1, =0x0C003FFF         ; mask 
        
    mrc  p15, 0, r0, c1, c0, 0   ; read
    and  r0, r0, r1              ; apply mask 
    bic  r0, r0, #0x08000000     ; clear bit 27
    bic  r0, r0, #0x00000400     ; clear bit 10
    orr  r0, r0, #0x78           ; ensure [6:3] = '1111'
    orr  r0, r0, #0x800          ; enable BTB
    mcr  p15, 0, r0, c1, c0, 0   ; write back

    ldmfd   sp!, {r0-r1}
   
  IF Interworking :LOR: Thumbing
    bx  lr
  ELSE
    mov  pc, lr          ; return
  ENDIF
   


;-------------------------------------------------------------------------------
;
; EnableL1DCache: Enables the L1 d$.  Does a global invalidate first.
;
; Inputs: None.
; 
; On return: N/A.
;
; Register used: r0, r1.  Stacked on caller's stack.
;
;-------------------------------------------------------------------------------
;
    ALIGN
    LEAF_ENTRY EnableL1DCache
    
    stmfd   sp!, {r0-r1}
    
    mcr  p15, 0, r0, c7, c6, 0   ; flush L1d$.  R0 is ignored.
        
    ldr  r1, =0x0C003FFF         ; mask 
        
    mrc  p15, 0, r0, c1, c0, 0   ; read
    and  r0, r0, r1              ; apply mask 
    bic  r0, r0, #0x08000000     ; clear bit 27
    bic  r0, r0, #0x00000400     ; clear bit 10
    orr  r0, r0, #0x78           ; ensure [6:3] = '1111'
    orr  r0, r0, #0x4            ; enable L1d$
    mcr  p15, 0, r0, c1, c0, 0   ; write back

    ldmfd   sp!, {r0-r1}
     
  IF Interworking :LOR: Thumbing
    bx  lr
  ELSE
    mov  pc, lr          ; return
  ENDIF
    

;-------------------------------------------------------------------------------
;
; EnableL1ICache: Enables the L1 i$.  Does a global invalidate first.
;
; Inputs: None.
; 
; On return: N/A.
;
; Register used: r0, r1.  Stacked on caller's stack.
;
;-------------------------------------------------------------------------------
;
    ALIGN
    LEAF_ENTRY EnableL1ICache
    
    stmfd   sp!, {r0-r1}
    
    mcr  p15, 0, r0, c7, c5, 0   ; flush L1i$ and BTB.  R0 is ignored.
        
    ldr  r1, =0x0C003FFF         ; mask 
        
    mrc  p15, 0, r0, c1, c0, 0   ; read
    and  r0, r0, r1              ; apply mask 
    bic  r0, r0, #0x08000000     ; clear bit 27
    bic  r0, r0, #0x00000400     ; clear bit 10
    orr  r0, r0, #0x78           ; ensure [6:3] = '1111'
    orr  r0, r0, #0x1000         ; enable L1i$
    mcr  p15, 0, r0, c1, c0, 0   ; write back

    ldmfd   sp!, {r0-r1}
     
  IF Interworking :LOR: Thumbing
    bx  lr
  ELSE
    mov  pc, lr          ; return
  ENDIF



;-------------------------------------------------------------------------------
;
; WritePwrMode: Write to PWRMODE co-processor.  Must be in privileged mode.
;
; Inputs: r0=pattern to write
; 
; On return: N/A.
;
; Register used: N/A
;
;-------------------------------------------------------------------------------
;
    ALIGN
    LEAF_ENTRY WritePwrMode

    mcr     p14, 0, r0, c7, c0, 0           ; Enter Idle mode

  IF Interworking :LOR: Thumbing
    bx  lr
  ELSE
    mov  pc, lr          ; return
  ENDIF



;------------------------------------------------------------------------------

    END 

